/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package gridworld_v04;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
import javax.swing.JButton;

/**
 *
 * @author Jonah
 */
public class Tile extends JButton implements ActionListener {

    /*implementation comment*/
    ////<editor-fold defaultstate="collapsed" desc="Static Variables">
    //</editor-fold>
    ////<editor-fold desc="Instanced Variables">
    private Game game;
    private Board board;
    private Integer[] neighborsIndex = new Integer[9];//think of this as a 3x3 grid with the center tile (tile[4]) representing this tile
    private ArrayList<Tile> neighbors = new ArrayList<Tile>();
    private ArrayList<Actor> occupants = new ArrayList<Actor>();
    private GWimages icons;
    public boolean Invalid = false;
    
    public ArrayList<Tile> getNeighbors() {
        return neighbors;
    }
    public ArrayList<Actor> getOccupants() {
        return occupants;
    }
    //</editor-fold>
    
    ////<editor-fold defaultstate="collapsed" desc="Constructor">
    public Tile(Integer index, Game game, Board board, GWimages icons) {
        neighborsIndex[4] = index;
        this.game = game;
        this.icons = icons;
        this.board = board;
        
        addActionListener(this);
    }
    //</editor-fold>
    ////<editor-fold defaultstate="collapsed" desc="Class Methods">
    public void addOccupant(Actor o){
        occupants.add(o);
        processOccupants();
    }
    public void removeOccupant(Actor o){
        occupants.remove(o);
        processOccupants();
    }
    
    /**
     * I still need to add a way to keep the user from placing multiple similar occupants on the same tile
     */
    public boolean checkOccupantType(TileEnum type, Tile tile){
        switch (type){
            case Bug:
                for (Actor o : tile.getOccupants()){
                    if (o instanceof Bug)
                        return true;
                }
                break;
            case Flower:
                for (Actor o : tile.getOccupants()){
                    if (o instanceof Flower)
                        return true;
                }
                break;
            case Rock:
                for (Actor o : tile.getOccupants()){
                    if (o instanceof Rock)
                        return true;
                }
                break;
            case Critter:
                for (Actor o : tile.getOccupants()){
                    if (o instanceof Critter)
                        return true;
                }
                break;
            default:return false;
        }
        return false;
    }
    public void processOccupants(){
        boolean rock = false, flower = false, bug = false, critter = false;
        if (occupants.isEmpty()){
            setIcon(null);
            return;
        }
        outerloop:
        {
            for (Actor o : occupants){
                if (o instanceof Rock){
                    rock = true;
                }
                if (o instanceof Flower){
                    flower = true;
                }
                if (o instanceof Bug){
                    bug = true;
                }
                if (o instanceof Critter){
                    critter = true;
                }
            }
            innerloop:
            {
                if (rock) { 
                    for (Actor o : occupants){
                        //if actor is not a rock or a bug then it shouldn't be here
                        if (!((o instanceof Rock) || (o instanceof Bug))){
                            o.remove();
                            break innerloop;
                        }
                    }
                }
                if (critter){
                    //critters destroy bugs and flowers
                    for (Actor o : occupants){
                        if (!(o instanceof Critter)){
                            o.remove();
                            break innerloop;
                        }
                    }
                }
            }

            if (rock) {
                setIcon(icons.rockIcon); //will show whenever there is a rock
                break outerloop;
            }
            if (critter){
                setIcon(icons.critterIcon);//will show up whenever there is a critter present
                break outerloop;
            }
            if (bug){
                setIcon(icons.bugIcon);
                break outerloop;
            }
            if (flower){
                setIcon(icons.flowerIcon);//will show if only flower is present
            }
            if ((!rock) && (!flower) && (!bug) && (!critter)){
                setIcon(null);
            }
        }
        removeDuplicates();
        //System.out.println("processed tile :" + toString());
    }
    private void removeDuplicates(){
        boolean flower = false, bug = false, critter = false, rock = false;
        loop:
            for (int i = 0; i < occupants.size(); i++){
                if (occupants.get(i)instanceof Rock ){
                    if (!rock){
                        rock = true;
                        continue;
                    } else {
                        occupants.get(i).remove();
                        continue;
                    }
                }else if (occupants.get(i)instanceof Bug ){
                    if (!bug){
                        bug = true;
                        continue loop;
                    } else {
                        occupants.get(i).remove();
                        continue loop;
                    }
                }else if (occupants.get(i)instanceof Critter ){
                    if (!critter){
                        critter = true;
                        continue loop;
                    } else {
                        occupants.get(i).remove();
                        continue loop;
                    }
                }else if (occupants.get(i)instanceof Flower ){
                    if (!flower){
                        flower = true;
                        continue loop;
                    } else {
                        occupants.get(i).remove();
                        continue loop;
                    }
                }
            }
    }
//    public void removeTileOccupant(Actor actor){
//        occupants.remove(actor);
//    }
    public void generateNieghbors( int rows, int cols){
        for (Integer i : neighborsIndex){
            i = null;
        } //defaults to null

        if (neighborsIndex[4] > cols) {
            neighborsIndex[1] = (Integer)(neighborsIndex[4] - cols);
        }
        if (neighborsIndex[4] < cols*(rows-1)){
            neighborsIndex[7] = (Integer)(neighborsIndex[4] + cols);
        }
        if ((neighborsIndex[4] % cols)!=0){
            neighborsIndex[3] = (Integer)(neighborsIndex[4] - 1);
        }
        if ((neighborsIndex[4]%cols)!=(cols-1)){
            neighborsIndex[5] = (Integer)(neighborsIndex[4] + 1);
        }
        if ((neighborsIndex[1]!=null)&&(neighborsIndex[3]!=null)){
            neighborsIndex[0] =  (Integer)((neighborsIndex[4] - cols) - 1);
        }
        if ((neighborsIndex[1]!=null)&&(neighborsIndex[5]!=null)){
            neighborsIndex[2] =  (Integer)((neighborsIndex[4] - cols) + 1);
        }
        if ((neighborsIndex[7]!=null)&&(neighborsIndex[3]!=null)){
            neighborsIndex[6] =  (Integer)((neighborsIndex[4] + cols) - 1);
        }
        if ((neighborsIndex[7]!=null)&&(neighborsIndex[5]!=null)){
            neighborsIndex[8] =  (Integer)((neighborsIndex[4] + cols) + 1);
        }
        
        //sets up the reference to valid neighbors
        //System.out.print("neighborsIndex size = "+ neighborsIndex.length + "  :");
//        for (Integer i : neighborsIndex){
//            System.out.print(i + ", ");
//        }
        //System.out.println();
        //System.out.println(board.getTile(0).Invalid);
        for (Integer i : neighborsIndex){
            //System.out.println(i);
            if (i != null){
                if (!(board.getTile((int)i).Invalid)){
                    neighbors.add(board.getTile(i));
                }
            }
        }
    }
    @Override public String toString() {
        return "Tile" + neighborsIndex[4] + '{'+ occupants.toString() +'}';
    }
    //</editor-fold>
    ////<editor-fold defaultstate="collapsed" desc="Interface Override Methods">
    //</editor-fold>

    @Override
    public void actionPerformed(ActionEvent e) {
        //System.out.println("tile clicked: " +  toString());
        game.processTileClick(this);
    }
}
